
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections;
using System.Reflection;
using System.Security.Policy;

using Swaf.BizObj;
using Swaf.Config;


namespace Swaf
{
	/// <summary>
	/// Summary description for IsolatedApplication.
	/// </summary>
	public class IsolatedApplication
	{
		protected AppDomain m_isolatedDomain;
		protected AppHelper m_helper;

		public IsolatedApplication(string name, string SwafConfigFile, string appBaseDirectory, string p1, string p2, bool inBrowseMode)
		{
			// Set up the AppDomainSetup
			AppDomainSetup setup = new AppDomainSetup();
			setup.ApplicationBase = appBaseDirectory;

			// Set up the Evidence
			Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
			Evidence evidence = new Evidence(baseEvidence);

			// Create the AppDomain      
			m_isolatedDomain = AppDomain.CreateDomain(name, evidence, setup);
			m_helper = (AppHelper)m_isolatedDomain.CreateInstanceAndUnwrap(typeof(IsolatedApplication).Assembly.FullName, "Swaf.AppHelper", false, BindingFlags.Default, null,
				new object[]{SwafConfigFile,p1,p2, inBrowseMode},null,null,null);
			Application thisApp = (Application) Application.currentApp;
			thisApp.OnAppShutdown += new AppShutdownRequest(stop);
		}

		public void shutdown()
		{
			((IAppManagement)m_helper.App).shutdown();
			AppDomain.Unload(m_isolatedDomain);
			System.Diagnostics.EventLog.WriteEntry("Swaf.IsolatedApplication.shutdown","IsolatedApplication successfully shutdown.");
		}
		public void stop(IApplication app)
		{
			shutdown();
		}

		public IApplication App {get{return m_helper.App;}}
	}

    public class AppHelper : MarshalByRefObject
	{
		public IApplication App;

		public AppHelper(string configFile, string p1, string p2, bool inBrowseMode)
		{
			if(!inBrowseMode)
				App = Application.create(configFile,p1,p2);
			else
				App = Application.createInBrowseMode(configFile,p1,p2);
		}
	}

	public class IsolatedApplicationManager : IConfigPartner
	{
		protected IDictionary m_apps;

		public IsolatedApplicationManager(IApplication app)
		{
			m_apps = new Hashtable();
		}

		internal void addIsolatedApp(string name, string configFile, string binDirectory, string localConfigHome, string webconfigHome)
		{
			m_apps[name] = new IsolatedApplication(name, configFile, binDirectory, localConfigHome, webconfigHome, false);
		}

		#region IConfigPartner Members
		public void checkConfigStatus()
		{
			// TODO:  Add IsolatedApplicationConfigPartner.checkConfigStatus implementation
		}

		public void registerForConfig(IConfigManager config)
		{
			config.registerHandler("<IsolatedApplications> <App>", new IsoAppConfigHandler(this));
			((IAppManagement)Application.currentApp).OnAppShutdown += new AppShutdownRequest(IsolatedApplicationManager_OnAppShutdown);
		}
		#endregion

		protected internal class IsoAppConfigHandler : ConfigHandler
		{
			protected IsolatedApplicationManager m_mgr;
			protected static string[] s_legalAttributes = new string[]{"name","configFile", "binDirectory","localConfigHome", "webConfigHome"};
			public IsoAppConfigHandler(IsolatedApplicationManager mgr)
			{
				m_mgr = mgr;
			}
			public override void executeBefore(IConfigElement configInfo)
			{
				IApplication app = Application.currentApp;
				configInfo.checkIllegalAttributes(s_legalAttributes);
				string name = configInfo.getAttribute("name");
				string configFile = configInfo.getAttribute("configFile");
				string binDirectory = configInfo.getAttribute("binDirectory");
				string localConfigHome = configInfo.getAttribute("localConfigHome");
				string webConfigHome = configInfo.getAttribute("webConfigHome");
				if(name != null && configFile != null && binDirectory != null && localConfigHome != null && webConfigHome != null)
				{
					m_mgr.addIsolatedApp(name, configFile, binDirectory, localConfigHome, webConfigHome);
					Application.currentApp.Log.println(Application.VERBOSE_STARTUP_LOG_LEVEL,"Read configuration entry for IsolatedApplication: Name={0}, ConfigFile={1}, BinDirectory={2}, LocalConfigHome={3}, WebConfigHome={4}", name, configFile, binDirectory, localConfigHome, webConfigHome);
				}

			}
		}

		internal IDictionary Applications {get{return m_apps;}}

		private void IsolatedApplicationManager_OnAppShutdown(IApplication app)
		{
			foreach(IsolatedApplication isoApp in m_apps.Values)
				isoApp.shutdown();
		}

	}

	public class IsolatedApplicationManagerRules
	{
		public IBizObjList getConfiguredApplications(IApplication app, IDictionary context, string dummy)
		{
			IsolatedApplicationManager mgr = (IsolatedApplicationManager)app.appData["sysObjs-IsolatedAppMgr"];
			return null;
		}

		public bool addApplication(IApplication app, IDictionary context, IBizObj appInfo)
		{
			return false;
		}

		public bool removeApplication(IApplication app, IDictionary context, string appName)
		{
			return false;
		}

		public bool stopApplication(IApplication app, IDictionary context, string appName)
		{
			return false;
		}

		public bool startApplication(IApplication app, IDictionary context, string appName)
		{
			return false;
		}
	}
}
